home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / os2 / adaptor.zip / ADAPT.ZIP / adaptor / dalib / pvm3 / schedul1.c < prev    next >
C/C++ Source or Header  |  1993-11-29  |  52KB  |  1,567 lines

  1. /**************************************************************************
  2. *                                                                         *
  3. *  Author      : Dr. Thomas Brandes, GMD, I1.HR                           *
  4. *  Copyright   : GMD St. Augustin, Germany                                *
  5. *  Date        : Apr 92                                                   *
  6. *  Last Update : May 92                                                   *
  7. *                                                                         *
  8. *  This Module is part of the DALIB                                       *
  9. *                                                                         *
  10. *  Module      : schedule.c                                               *
  11. *                                                                         *
  12. *  Function    : Operations for indirect addressing of distributed arrays *
  13. *                                                                         *
  14. *  Export : FORTRAN Interface                                             *
  15. *                                                                         *
  16. *  - A, P, Q, ... are conform and are distributed                         *
  17. *  - B is indirect accessed, rank determines number of P, Q, ...          *
  18. *  - A and B have same type                                               *
  19. *                                                                         *
  20. *  A = B [P]  : A[j] = B[P[j]]    for all j                               *
  21. *                                                                         *
  22. *  void dalib_global_getm1_ (a, a_size, a_elems,                          *
  23. *                            b, b_N1, p, mask   )                         *
  24. *                                                                         *
  25. *  B [P] = A  : B[P[j]] = A[j]    for all j                               *
  26. *                                                                         *
  27. *  void dalib_global_setm1_ (op, b, b_N1, p,                              *
  28. *                            a, a_size, a_elems, mask)                    *
  29. *                                                                         *
  30. *  A = B [P,Q]  : A[j] = B[P[j],Q[j]]    for all j                        *
  31. *                                                                         *
  32. *  void dalib_global_getm2_ (a, a_size, a_elems,                          *
  33. *                            b, b_N1, b_N2, p, q, mask   )                *
  34. *                                                                         *
  35. *  B [P,Q] = A  : B[P[j],Q[j]] = A[j]    for all j                        *
  36. *                                                                         *
  37. *  void dalib_global_setm2_ (op, b, b_N1, b_N2, p, q,                     *
  38. *                            a, a_size, a_elems, mask)                    *
  39. *                                                                         *
  40. **************************************************************************/
  41.  
  42. #undef DEBUG
  43. #include "system.h"
  44. #include <stdio.h>
  45.  
  46. /*********************************************************
  47. *                                                        *
  48. *  Global data for a schedule                            *
  49. *                                                        *
  50. *********************************************************/
  51.  
  52.   /******************************************************************
  53.   *                                                                 *
  54.   *  send_schedule                                                  *
  55.   *  -------------------------------------------------------------  *
  56.   *  | s_no[0]      | s_no[1]     |                  | s_no[k-1] |  *
  57.   *  -------------------------------------------------------------  *
  58.   * /\             /\            /\                 /\              *
  59.   *  | s_ptr[0]     | s_ptr[1]       .......         | s_ptr[k-1]   *
  60.   *                                                                 *
  61.   *                                                                 *
  62.   *  s_no[p-1] : number of indexes that point to process p          *
  63.   *                                                                 *
  64.   *  send_schedule [s_ptr[p-1]]                 index values        *
  65.   *  send_schedule [s_ptr[p-1]+1]               that point to       *
  66.   *  send_schedule [s_ptr[p-1]+2]               process p           *
  67.   *  ............................                                   *
  68.   *  send_schedule [s_ptr[p-1]+s_no[p-1]-1]                         *
  69.   *                                                                 *
  70.   *  send_values : size of array send_schedule                      *
  71.   *                                                                 *
  72.   *  index[i] is in send_schedule[local_index[i]]                    *
  73.   *                                                                 *
  74.   ******************************************************************/
  75.  
  76.   int index_values;    /* number of elements in index, local part */
  77.   int send_values;     /* number of true index elements, mask!    */
  78.   int *send_schedule;  /* size is send_values */
  79.   int *s_ptr;          /* size is nproc()     */
  80.   int *s_no;           /* size is nproc()     */
  81.  
  82.   int *local_index;    /* size is send_values */
  83.  
  84.   /******************************************************************
  85.   *                                                                 *
  86.   *  recv_schedule                                                  *
  87.   *  -------------------------------------------------------------  *
  88.   *  | r_no[0]      | r_no[1]     |                  | r_no[k-1] |  *
  89.   *  -------------------------------------------------------------  *
  90.   * /\             /\            /\                 /\              *
  91.   *  | r_ptr[0]     | r_ptr[1]       .......         | r_ptr[k-1]   *
  92.   *                                                                 *
  93.   *                                                                 *
  94.   *  r_no[p-1] : number of indexes of process p that point to me    *
  95.   *                                                                 *
  96.   *  recv_schedule [r_ptr[p-1]]                 index values        *
  97.   *  recv_schedule [r_ptr[p-1]+1]               of process p that   *
  98.   *  recv_schedule [r_ptr[p-1]+2]               point to values     *
  99.   *  ............................               belonging to        *
  100.   *  recv_schedule [r_ptr[p-1]+r_no[p-1]-1]     this process        *
  101.   *                                                                 *
  102.   *  recv_values : size of array recv_schedule                      *
  103.   *                                                                 *
  104.   ******************************************************************/
  105.  
  106.   int recv_values;
  107.   int *recv_schedule;
  108.   int *r_ptr;
  109.   int *r_no;
  110.  
  111.   int operation;   /* operation for global set, 0 - 18 */
  112.  
  113. /*********************************************************
  114. *                                                        *
  115. *  ERROR - Handling                                      *
  116. *                                                        *
  117. *********************************************************/
  118.  
  119. void dalib_schedule_error (s)
  120. char s[];
  121. { printf ("FATAL ERROR : dalib_schedule_...\n");
  122.   printf ("Message : %s\n", s);
  123.   exit (-1);
  124. }
  125.  
  126. #ifdef DEBUG
  127. /*********************************************************
  128. *                                                        *
  129. *  P R I N T I N G    T E S T    O U T P U T             *
  130. *                                                        *
  131. *********************************************************/
  132.  
  133. void dalib_print_send_schedule ()
  134.  
  135. { int k;
  136.  
  137.   /* lock (&sm->global_lock); */
  138.  
  139.   /* print the send_schedule */
  140.  
  141.   printf ("Process %d has %d of %d pointers to other values\n",
  142.            pcb.i, send_values, index_values);
  143.  
  144.   for (k=0; k<pcb.p; k++)
  145.       printf ("Process %d needs %d values of process %d\n",
  146.               pcb.i, s_no[k], k+1);
  147.  
  148.   /* unlock (&sm->global_lock); */
  149. }
  150.  
  151. void dalib_print_recv_schedule ()
  152.  
  153. { int k;
  154.  
  155.   /* lock (&sm->global_lock); */
  156.  
  157.   /* print the recv_schedule */
  158.  
  159.   printf ("Process %d has %d pointers from other ones to its values\n",
  160.            pcb.i, recv_values);
  161.  
  162.   for (k=0; k<pcb.p; k++)
  163.       printf ("Process %d has %d indexes of process %d\n",
  164.               pcb.i, r_no[k], k+1);
  165.  
  166.   /* unlock (&sm->global_lock); */
  167. }
  168.  
  169. void dalib_print_send_sched_values ()
  170.  
  171. { /* print the send_schedule */
  172.  
  173.   int j;
  174.  
  175.   /* lock (&sm->global_lock); */
  176.  
  177.   printf ("send_schedule of process %d \n", pcb.i);
  178.   printf ("=========================== \n");
  179.  
  180.   printf ("\n");
  181.   printf ("send values = %d\n", send_values);
  182.   printf ("\n");
  183.   for (j=0;j<pcb.p;j++)
  184.     printf ("proc %d: ptr = %d, no = %d \n", j+1, s_ptr[j], s_no[j]);
  185.    
  186.   printf ("\n");
  187.   for (j=0;j<send_values;j++)
  188.     printf ("send_schedule (%d) = %d\n", j, send_schedule[j]);
  189.   printf ("\n");
  190.  
  191.   /* unlock (&sm->global_lock); */
  192.  
  193. } /* dalib_print_send_sched_values */
  194.  
  195.  
  196. void dalib_print_recv_sched_values ()
  197.  
  198. { /* print the recv schedule */
  199.  
  200.   int j;
  201.  
  202.   /* lock (&sm->global_lock); */
  203.  
  204.   printf ("recv_schedule of process %d \n", pcb.i);
  205.   printf ("=========================== \n");
  206.  
  207.   printf ("\n");
  208.   for (j=0;j<pcb.p;j++)
  209.     printf ("proc %d: ptr = %d , no = %d \n", j+1, r_ptr[j], r_no[j]);
  210.    
  211.   printf ("\n");
  212.   printf ("recv_values = %d\n", recv_values);
  213.   printf ("\n");
  214.  
  215.   for (j=0;j<recv_values;j++)
  216.     printf ("recv_schedule(%d,%d) = %d\n", pcb.i, j, recv_schedule[j]);
  217.   printf ("\n");
  218.  
  219.   /* unlock (&sm->global_lock); */
  220.  
  221. } /* dalib_print_recv_sched_values */
  222.  
  223. #endif
  224.  
  225. /*********************************************************
  226. *                                                        *
  227. *  Help function to determine fictive zero of array      *
  228. *                                                        *
  229. *********************************************************/
  230.  
  231. unsigned char * dalib_array_zero1 (a, a_size, a_N1)
  232. unsigned char *a;
  233. int a_size, a_N1;
  234.  
  235. { int lb, ub, offset;
  236.  
  237.   /* determination of offset */
  238.  
  239.   dalib_local_extensions (pcb.i, a_N1, &lb, &ub);
  240.  
  241.   offset = (lb - 1) * a_size;
  242.   return (a - offset);
  243. }
  244.  
  245.  
  246. unsigned char *dalib_array_zero2 (a, a_size, a_N1, a_N2)
  247. unsigned char *a;
  248. int a_size, a_N1, a_N2;
  249.  
  250. { int lb, ub, offset;
  251.  
  252.   /* determination of offset */
  253.  
  254.   dalib_local_extensions (pcb.i, a_N2, &lb, &ub);
  255.  
  256.   offset = a_N1 * (lb - 1);
  257.   offset = offset * a_size;
  258.   return (a - offset);
  259. }
  260.  
  261. /*********************************************************
  262. *                                                        *
  263. *  PROCEDURES for global SET                             *
  264. *                                                        *
  265. *********************************************************/
  266.  
  267.           /*************************************
  268.           *                                    *
  269.           *  C O P Y                           *
  270.           *                                    *
  271.           *************************************/
  272.  
  273. void dalib_set_copy (a_zero, values, size)
  274. unsigned char *a_zero, *values;
  275. int size;
  276.  
  277. { int i, j;
  278.   unsigned char *ptr;
  279.  
  280.   for (j=0; j<recv_values; j++)
  281.     { /* a[recv_schedule[j]] = values[j]  */
  282.       ptr = a_zero + recv_schedule[j] * size;
  283.       for (i=0;i<size;i++)
  284.         ptr[i] = values[j*size + i];
  285.     }
  286. } /* dalib_set_copy */
  287.  
  288.           /*************************************
  289.           *                                    *
  290.           *  M I N V A L                       *
  291.           *                                    *
  292.           *************************************/
  293.  
  294. void dalib_set_min_ints (a_zero, values)
  295. int *a_zero, *values;
  296.  
  297. { int j;
  298.   int *ptr;
  299.  
  300.   for (j=0; j<recv_values; j++)
  301.     { /* a[recv_schedule[j]] = min (a[recv-schedule[j], values[j])  */
  302.       ptr = a_zero + recv_schedule[j];
  303.       if (values[j] < *ptr) *ptr = values[j];
  304.     }
  305. } /* dalib_set_min_ints */
  306.  
  307. void dalib_set_min_reals (a_zero, values)
  308. float *a_zero, *values;
  309.  
  310. { int j;
  311.   float *ptr;
  312.  
  313.   for (j=0; j<recv_values; j++)
  314.     { /* a[recv_schedule[j]] = min (a[recv-schedule[j], values[j])  */
  315.       ptr = a_zero + recv_schedule[j];
  316.       if (values[j] < *ptr) *ptr = values[j];
  317.     }
  318. } /* dalib_set_min_ints */
  319.  
  320. void dalib_set_min_doubles (a_zero, values)
  321. double *a_zero, *values;
  322.  
  323. { int j;
  324.   double *ptr;
  325.  
  326.   for (j=0; j<recv_values; j++)
  327.     { /* a[recv_schedule[j]] = min (a[recv-schedule[j], values[j])  */
  328.       ptr = a_zero + recv_schedule[j];
  329.       if (values[j] < *ptr) *ptr = values[j];
  330.     }
  331. } /* dalib_set_min_doubles */
  332.  
  333.           /*************************************
  334.           *                                    *
  335.           *  M A X V A L                       *
  336.           *                                    *
  337.           *************************************/
  338.  
  339. void dalib_set_max_ints (a_zero, values)
  340. int *a_zero, *values;
  341.  
  342. { int j;
  343.   int *ptr;
  344.  
  345.   for (j=0; j<recv_values; j++)
  346.     { /* a[recv_schedule[j]] = max (a[recv-schedule[j], values[j])  */
  347.       ptr = a_zero + recv_schedule[j];
  348.       if (values[j] > *ptr) *ptr = values[j];
  349.     }
  350. } /* dalib_set_max_ints */
  351.  
  352. void dalib_set_max_reals (a_zero, values)
  353. float *a_zero, *values;
  354.  
  355. { int j;
  356.   float *ptr;
  357.  
  358.   for (j=0; j<recv_values; j++)
  359.     { /* a[recv_schedule[j]] = max (a[recv-schedule[j], values[j])  */
  360.       ptr = a_zero + recv_schedule[j];
  361.       if (values[j] > *ptr) *ptr = values[j];
  362.     }
  363. } /* dalib_set_max_ints */
  364.  
  365. void dalib_set_max_doubles (a_zero, values)
  366. double *a_zero, *values;
  367.  
  368. { int j;
  369.   double *ptr;
  370.  
  371.   for (j=0; j<recv_values; j++)
  372.     { /* a[recv_schedule[j]] = max (a[recv-schedule[j], values[j])  */
  373.       ptr = a_zero + recv_schedule[j];
  374.       if (values[j] > *ptr) *ptr = values[j];
  375.     }
  376. } /* dalib_set_max_doubles */
  377.  
  378.           /*************************************
  379.           *                                    *
  380.           *  S U M                             *
  381.           *                                    *
  382.           *************************************/
  383.  
  384. void dalib_set_add_ints (a_zero, values)
  385. int *a_zero, *values;
  386.  
  387. { int j;
  388.   int *ptr;
  389.  
  390.   for (j=0; j<recv_values; j++)
  391.     { /* a[recv_schedule[j]] = a[recv-schedule[j] + values[j]  */
  392.       ptr = a_zero + recv_schedule[j];
  393.       *ptr += values[j];
  394.     }
  395. } /* dalib_set_add_ints */
  396.  
  397. void dalib_set_add_reals (a_zero, values)
  398. float *a_zero, *values;
  399.  
  400. { int j;
  401.   float *ptr;
  402.  
  403.   for (j=0; j<recv_values; j++)
  404.     { /* a[recv_schedule[j]] = a[recv-schedule[j] + values[j]  */
  405.       ptr = a_zero + recv_schedule[j];
  406.       *ptr += values[j];
  407.     }
  408. } /* dalib_set_add_reals */
  409.  
  410. void dalib_set_add_doubles (a_zero, values)
  411. double *a_zero, *values;
  412.  
  413. { int j;
  414.   double *ptr;
  415.  
  416.   for (j=0; j<recv_values; j++)
  417.     { /* a[recv_schedule[j]] = a[recv-schedule[j] + values[j]  */
  418.       ptr = a_zero + recv_schedule[j];
  419.       *ptr += values[j];
  420.     }
  421. } /* dalib_set_add_doubles */
  422.  
  423.           /*************************************
  424.           *                                    *
  425.           *  P R O D U C T                     *
  426.           *                                    *
  427.           *************************************/
  428.  
  429. void dalib_set_mult_ints (a_zero, values)
  430. int *a_zero, *values;
  431.  
  432. { int j;
  433.   int *ptr;
  434.  
  435.   for (j=0; j<recv_values; j++)
  436.     { /* a[recv_schedule[j]] = a[recv-schedule[j] * values[j]  */
  437.       ptr = a_zero + recv_schedule[j];
  438.       *ptr *= values[j];
  439.     }
  440. } /* dalib_set_mult_ints */
  441.  
  442. void dalib_set_mult_reals (a_zero, values)
  443. float *a_zero, *values;
  444.  
  445. { int j;
  446.   float *ptr;
  447.  
  448.   for (j=0; j<recv_values; j++)
  449.     { /* a[recv_schedule[j]] = a[recv-schedule[j] * values[j]  */
  450.       ptr = a_zero + recv_schedule[j];
  451.       *ptr *= values[j];
  452.     }
  453. } /* dalib_set_mult_reals */
  454.  
  455. void dalib_set_mult_doubles (a_zero, values)
  456. double *a_zero, *values;
  457.  
  458. { int j;
  459.   double *ptr;
  460.  
  461.   for (j=0; j<recv_values; j++)
  462.     { /* a[recv_schedule[j]] = a[recv-schedule[j] * values[j]  */
  463.       ptr = a_zero + recv_schedule[j];
  464.       *ptr *= values[j];
  465.     }
  466. } /* dalib_set_mult_doubles */
  467.  
  468.           /*************************************
  469.           *                                    *
  470.           *  AND, OR, EOR                      *
  471.           *                                    *
  472.           *************************************/
  473.  
  474. void dalib_set_and_ints (a_zero, values)
  475. int *a_zero, *values;
  476.  
  477. { int j;
  478.   int *ptr;
  479.  
  480.   for (j=0; j<recv_values; j++)
  481.     { /* a[recv_schedule[j]] = a[recv-schedule[j] & values[j]  */
  482.       ptr = a_zero + recv_schedule[j];
  483.       *ptr = *ptr | values[j];
  484.     }
  485. } /* dalib_set_and_ints */
  486.  
  487. void dalib_set_or_ints (a_zero, values)
  488. int *a_zero, *values;
  489.  
  490. { int j;
  491.   int *ptr;
  492.  
  493.   for (j=0; j<recv_values; j++)
  494.     { /* a[recv_schedule[j]] = a[recv-schedule[j] | values[j]  */
  495.       ptr = a_zero + recv_schedule[j];
  496.       *ptr = *ptr | values[j];
  497.     }
  498. } /* dalib_set_or_ints */
  499.  
  500. void dalib_set_eor_ints (a_zero, values)
  501. int *a_zero, *values;
  502.  
  503. { int j;
  504.   int *ptr;
  505.  
  506.   for (j=0; j<recv_values; j++)
  507.     { /* a[recv_schedule[j]] = a[recv-schedule[j] ^ values[j]  */
  508.       ptr = a_zero + recv_schedule[j];
  509.       *ptr = *ptr ^ values[j];
  510.     }
  511. } /* dalib_set_eor_ints */
  512.  
  513.           /*************************************
  514.           *                                    *
  515.           *  ALL, ANY, PARITY                  *
  516.           *                                    *
  517.           *************************************/
  518.  
  519. void dalib_set_or_bools (a_zero, values)
  520. int *a_zero, *values;
  521.  
  522. { int j;
  523.   int *ptr;
  524.  
  525.   for (j=0; j<recv_values; j++)
  526.     { /* a[recv_schedule[j]] = a[recv-schedule[j] || values[j]  */
  527.       ptr = a_zero + recv_schedule[j];
  528.       *ptr = *ptr || values[j];
  529.     }
  530. } /* dalib_set_or_bools */
  531.  
  532. void dalib_set_and_bools (a_zero, values)
  533. int *a_zero, *values;
  534.  
  535. { int j;
  536.   int *ptr;
  537.  
  538.   for (j=0; j<recv_values; j++)
  539.     { /* a[recv_schedule[j]] = a[recv-schedule[j] || values[j]  */
  540.       ptr = a_zero + recv_schedule[j];
  541.       *ptr = *ptr && values[j];
  542.     }
  543. } /* dalib_set_and_bools */
  544.  
  545. void dalib_set_neq_bools (a_zero, values)
  546. int *a_zero, *values;
  547.  
  548. { int j;
  549.   int *ptr;
  550.  
  551.   for (j=0; j<recv_values; j++)
  552.     { /* a[recv_schedule[j]] = a[recv-schedule[j] || values[j]  */
  553.       ptr = a_zero + recv_schedule[j];
  554.       if (values[j]) *ptr = !(*ptr);
  555.     }
  556. } /* dalib_set_neq_bools */
  557.  
  558. /*******************************************************************
  559. *                                                                  *
  560. *  dalib_schedule_init_ (b_N, index, index_size, mask)             *
  561. *                                                                  *
  562. *  Initialization of a schedule                                    *
  563. *                                                                  *
  564. *  in:  b_N (number of elements in the distributed dimension of b) *
  565. *       index (index values for array b)                           *
  566. *       index_size (number of elements on this processor)          *
  567. *       mask (mask for values to be indexed, mask == index pos)    *
  568. *                                                                  *
  569. *  out: index_values, send_values, recv_values                     *
  570. *       s_no, r_no                                                 *
  571. *                                                                  *
  572. *******************************************************************/
  573.  
  574. void dalib_schedule_init_ (b_N, index, index_elems, mask)
  575.  
  576. /* index must be pointer to distributed integer*4 array
  577.    index_elems is number of elements of index locally
  578.    b_N is number of elements in the distributed dimension
  579.    mask  must be pointer to distributed logical*4 array 
  580.    index == mask means there is no mask                  */
  581.  
  582. int *b_N, *index, *index_elems, *mask;
  583.  
  584. { int b_elems;
  585.   int id, nproc, p;    /* processor numbers */
  586.   int j, k;
  587.  
  588.   id = pcb.i;
  589.   nproc = pcb.p;
  590.  
  591.   index_values = *index_elems;
  592.  
  593. #ifdef DEBUG
  594.   printf ("Process %d starts schedule_init, b_N = %d, indexes = %d\n", 
  595.            id, *b_N, index_values);
  596. #endif
  597.  
  598.   /* intialize s_no */
  599.  
  600.   s_no = (int *) malloc (4 * nproc);
  601. #ifdef MEIKO_CS2
  602.   ew_touchBuf(s_no, sizeof(int)*nproc);
  603. #endif
  604.   for (k=0; k<nproc; k++)
  605.       s_no [k] = 0;
  606.  
  607.   local_index = (int *) malloc (4 * index_values);
  608.  
  609.   /* saves the processor ids */
  610.  
  611.   /* count number of sending values */
  612.  
  613.   b_elems  = *b_N;
  614.  
  615.   if (index == mask)       /* no mask */
  616.     { for (j=0; j < index_values;j++)
  617.        { /* which processor has b[index[j]] */
  618.          p = (index[j] * nproc - 1) / b_elems + 1;
  619.          local_index[j] = p;
  620.          /* make sure that p is between 1 and nproc */
  621.          if ((p<=0) || (p>nproc))
  622.           { printf ("Index value %d out of range\n", index[j]);
  623.             printf ("Fatal ERROR, will exit\n");
  624.             exit(-1);
  625.           }
  626.          s_no [p-1] += 1;
  627.        }
  628.       send_values = index_values;
  629.     }
  630.    else /* there is a mask */
  631.     { send_values = 0;
  632.       for (j=0; j< index_values;j++)
  633.        { if (mask[j])
  634.          { /* which processor has b[index[j]] */
  635.            p = (index[j] * nproc - 1) / b_elems + 1;
  636.            local_index[j] = p;
  637.            /* make sure that p is between 1 and nproc */
  638.            if ((p<=0) || (p>nproc))
  639.             { printf ("Index value %d out of range\n", index[j]);
  640.               printf ("Fatal ERROR, will exit\n");
  641.               exit(-1);
  642.             }
  643.            s_no [p-1] += 1;
  644.            send_values += 1;
  645.          }
  646.          else local_index[j] = -1;   /* not existing processor */
  647.        } /* for */
  648.     } /* with mask */
  649.  
  650.   /* now it is known how many elements of index have to be send */
  651.  
  652.   for (k=0; k<nproc; k++)
  653.       asend (id, k+1, s_no + k, 4);
  654.  
  655. # ifdef DEBUG
  656.   dalib_print_send_schedule ();
  657. # endif
  658.  
  659.   /* now it will be known how many elements other processors need */
  660.  
  661.   r_no = (int*) malloc (4 * nproc);
  662. #ifdef MEIKO_CS2
  663.   ew_touchBuf(r_no, nproc*sizeof(int));
  664. #endif
  665.   recv_values = 0;
  666.  
  667.   for (k=0; k<nproc; k++)
  668.     { areceive (id, k+1, r_no + k, 4);
  669.       recv_values += r_no[k];
  670.     }
  671.  
  672. # ifdef DEBUG
  673.   dalib_print_recv_schedule ();
  674. # endif
  675.  
  676.   /* now every process knows
  677.  
  678.       - how many of my indexes point to the other processors
  679.       - how many indexes of other processors point to me 
  680.   */
  681.  
  682. } /* dalib_schedule_init */
  683.  
  684. /*********************************************************
  685. *                                                        *
  686. *  dalib_schedule_send_ (b_N, index)                     *
  687. *                                                        *
  688. *  Definition of send_schedule, sending it               *
  689. *                                                        *
  690. *  in:  b_N  (number of elements of b in distrib. dim)   *
  691. *       index (index values for array b)                 *
  692. *                                                        *
  693. *  out: s_ptr, send_schedule                             *
  694. *       indexes will be send                             *
  695. *                                                        *
  696. *********************************************************/
  697.  
  698. void dalib_schedule_send_ (b_N, index)
  699.  
  700. int *b_N, *index;
  701.  
  702. { int id, nproc, p;    /* processor numbers */
  703.   int j, k;
  704.  
  705.   id = pcb.i;
  706.   nproc = pcb.p;
  707.  
  708.   /* make the s_ptr array */
  709.  
  710.   s_ptr = (int *) malloc (4 * nproc);
  711.   s_ptr[0] = 0;
  712.   for (k=1; k<nproc; k++)
  713.     { s_ptr [k] = s_ptr[k-1] + s_no [k-1]; 
  714.     }
  715.  
  716.   /* make the send_schedule and local_index array */
  717.  
  718.   send_schedule = (int *) malloc (4 * send_values);
  719. #ifdef MEIKO_CS2
  720.   ew_touchBuf(send_schedule, sizeof(int)*send_values);
  721. #endif
  722.  
  723.   for (j=0; j<index_values;j++)
  724.     { /* collect indexes in send_schedule, local_index */
  725.       p = local_index[j];
  726.       if (p >= 0)                   /* mask is hidden in local_index */
  727.         { local_index[j] = s_ptr[p-1];
  728.           send_schedule [s_ptr[p-1]] = index[j] - 1;
  729.           s_ptr[p-1] += 1;
  730.         }
  731.     }
  732.  
  733.   /* reset the s_ptr array */
  734.  
  735.   s_ptr[0] = 0;
  736.   for (k=1; k<nproc; k++)
  737.      s_ptr [k] = s_ptr[k-1] + s_no [k-1]; 
  738.  
  739.   /* send the index values that point to other processors  */
  740.  
  741.   for (k=0; k<nproc; k++)
  742.     if (s_no[k] > 0)
  743.       asend (id, k+1, send_schedule + s_ptr[k], s_no[k] * 4);
  744.  
  745. # ifdef DEBUG
  746.   dalib_print_send_sched_values ();
  747. # endif
  748.  
  749.   free (send_schedule);
  750.  
  751. } /* dalib_schedule_send */
  752.  
  753. /*********************************************************
  754. *                                                        *
  755. *  dalib_schedule_send2_ (b_N1, b_N2, index1, index2 )   *
  756. *                                                        *
  757. *  Definition of send_schedule, sending it               *
  758. *                                                        *
  759. *  in:  b_N (description of indexed array, rank = 2)     *
  760. *       index1 (index values for array b)                *
  761. *       index2 (index values for array b)                *
  762. *                                                        *
  763. *  out: s_ptr, send_schedule                             *
  764. *       indexes will be send                             *
  765. *                                                        *
  766. *********************************************************/
  767.  
  768. void dalib_schedule_send2_ (b_N1, b_N2, index1, index2)
  769.  
  770. int *b_N1, *b_N2, *index1, *index2;
  771.  
  772. { int id, nproc, p;    /* processor numbers */
  773.   int j, k;
  774.  
  775.   id = pcb.i;
  776.   nproc = pcb.p;
  777.  
  778.   /* make the s_ptr array */
  779.  
  780.   s_ptr = (int *) malloc (4 * nproc);
  781.   s_ptr[0] = 0;
  782.   for (k=1; k<nproc; k++)
  783.     { s_ptr [k] = s_ptr[k-1] + s_no [k-1]; 
  784.     }
  785.  
  786.   /* make the send_schedule and local_index array */
  787.  
  788.   send_schedule = (int *) malloc (4 * send_values);
  789. #ifdef MEIKO_CS2
  790.   ew_touchBuf(send_schedule, sizeof(int)*send_values);
  791. #endif
  792.  
  793.   for (j=0; j<index_values;j++)
  794.     { /* collect indexes in send_schedule, local_index */
  795.       p = local_index[j];
  796.       if (p >= 0)                  /* mask is hidden in local_index */
  797.         { local_index[j] = s_ptr[p-1];
  798.           send_schedule [s_ptr[p-1]] =   (index2[j] - 1) * *b_N1
  799.                                        + (index1[j] - 1) ;
  800.           s_ptr[p-1] += 1;
  801.         }
  802.     }
  803.  
  804.   /* reset the s_ptr array */
  805.  
  806.   s_ptr[0] = 0;
  807.   for (k=1; k<nproc; k++)
  808.      s_ptr [k] = s_ptr[k-1] + s_no [k-1]; 
  809.  
  810.   /* send the index values that point to other processors  */
  811.  
  812.   for (k=0; k<nproc; k++)
  813.     if (s_no[k] > 0)
  814.       asend (id, k+1, send_schedule + s_ptr[k], s_no[k] * 4);
  815.  
  816. # ifdef DEBUG
  817.   dalib_print_send_sched_values ();
  818. # endif
  819.  
  820.   free (send_schedule);
  821.  
  822. } /* dalib_schedule_send2 */
  823.  
  824. /*********************************************************
  825. *                                                        *
  826. *  dalib_schedule_recv_ ()                               *
  827. *                                                        *
  828. *  Definition of recv_schedule, receiving it             *
  829. *                                                        *
  830. *  out: s_ptr, send_schedule                             *
  831. *       indexes will be send                             *
  832. *                                                        *
  833. *********************************************************/
  834.  
  835. void dalib_schedule_recv_ ()
  836.  
  837. { int id, nproc;
  838.   int j, k;
  839.  
  840.   id = pcb.i;
  841.   nproc = pcb.p;
  842.  
  843.   /* make the r_ptr array */
  844.  
  845.   r_ptr = (int *) malloc (4 * nproc);
  846.  
  847.   /* set r_ptr by using numbers of r_no */
  848.  
  849.   r_ptr[0] = 0;
  850.   for (k=1; k<nproc; k++)
  851.     r_ptr [k] = r_ptr[k-1] + r_no [k-1]; 
  852.  
  853.   /* make the recv_schedule array */
  854.  
  855.   recv_schedule = (int *) malloc (recv_values * 4);
  856. #ifdef MEIKO_CS2
  857.   ew_touchBuf(recv_schedule, sizeof(int)*recv_values);
  858. #endif
  859.  
  860.   /* receive the indexes */
  861.  
  862.   for (k=0; k<nproc; k++)
  863.     if (r_no[k] > 0)
  864.        areceive (id, k+1, recv_schedule + r_ptr[k], r_no[k] * 4);
  865.  
  866. # ifdef DEBUG
  867.   dalib_print_recv_sched_values ();
  868. # endif
  869.  
  870. } /* dalib_schedule_recv */
  871.  
  872. /*********************************************************
  873. *                                                        *
  874. *  dalib_switching_init_ (b_N, index, index_elems)       *
  875. *                                                        *
  876. *  Initialization of a schedule of switching             *
  877. *                                                        *
  878. *  in:  b_N (siye of b in distributed dimension)         *
  879. *       index (index values for array b)                 *
  880. *       index_elems (number of elems of A, index)        *
  881. *                                                        *
  882. *  out: send_values, recv_values                         *
  883. *       s_no, r_no                                       *
  884. *                                                        *
  885. *********************************************************/
  886.  
  887. void dalib_switching_init_ (b_N, index, index_elems)
  888. int *b_N;
  889. int *index;
  890. int *index_elems;
  891.  
  892. /* index must be pointer to distributed integer*4 array */
  893.  
  894. { int id, nproc, p;    /* processor numbers */
  895.   int j, k;
  896.   int b_elems;         /* is equal *b_N     */
  897.  
  898.   id = pcb.i;
  899.   nproc = pcb.p;
  900.  
  901.   index_values = *index_elems;
  902.   send_values = index_values;          /* no mask in this case */
  903.   
  904.   /* intialize s_no */
  905.  
  906.   s_no = (int *) malloc (4 * nproc);
  907.   for (k=0; k<nproc; k++)
  908.       s_no [k] = 0;
  909.  
  910.   local_index   = (int *) malloc (4 * index_values);
  911.  
  912.   /* saves the processor ids */
  913.  
  914.   /* count number of sending values */
  915.  
  916.   b_elems  = *b_N;
  917.  
  918.   for (j=0; j<index_values;j++)
  919.     { /* which processor has b[index[j]] */
  920.       p = (index[j] * nproc - 1) / b_elems + 1;
  921.       local_index[j] = p;
  922.       /* make sure that p is between 1 and nproc */
  923.       if ((p<=0) || (p>nproc))
  924.        { printf ("Index value %d out of range\n", index[j]);
  925.          printf ("Fatal ERROR, will exit\n");
  926.          exit(-1);
  927.        }
  928.       s_no [p-1] += 1;
  929.     }
  930.  
  931.   /* now it is known how many elements of index have to be send and recvd */
  932.  
  933.   /* now it will be known how many elements other processors need */
  934.  
  935.   r_no = (int*) malloc (4 * nproc);
  936.   recv_values = send_values ;
  937.  
  938.   for (k=0; k<nproc; k++)
  939.     r_no[k] = s_no[k];
  940.  
  941. } /* dalib_switching_init */
  942.  
  943. /*********************************************************
  944. *                                                        *
  945. *  dalib_schedule_get_send (b_zero, b_size)              *
  946. *                                                        *
  947. *  - send the requrested values of b to other processes  *
  948. *                                                        *
  949. *  in :   - b_zero : my fiktive zero address of b        *
  950. *         - b_size : number of bytes of one elem in b    *
  951. *                                                        *
  952. *  - uses recv_schedule that tells which elements        *
  953. *    are needed by the other processors                  *
  954. *                                                        *
  955. *  - done by building array of values and sending it     *
  956. *                                                        *
  957. *********************************************************/
  958.  
  959. void dalib_schedule_get_send_ (b_zero, b_size)
  960.  
  961. unsigned char *b_zero;  /* fiktive zero address of b            */
  962. int *b_size;            /* number of bytes for one element of b */
  963.  
  964. { int id, nproc;
  965.   int j, k, i;
  966.   int size;
  967.  
  968.   unsigned char *values;     /* arrays with the values */
  969.   unsigned char *ptr;        /* pointer for copy values */
  970.  
  971.   id = pcb.i;
  972.   nproc = pcb.p;
  973.  
  974.   /* Step 1: use recv_schedudule to get values needed by other processes */
  975.  
  976.   /* size of one element of array b */
  977.  
  978.   size = *b_size;
  979.  
  980.   values = (unsigned char *) malloc (recv_values * size);
  981.  
  982.   if (size == 4)
  983.     dalib_memget4 (values, b_zero, recv_schedule, recv_values);
  984.   else if (size == 8)
  985.     dalib_memget8 (values, b_zero, recv_schedule, recv_values);
  986.   else
  987.     { for (j=0;j<recv_values;j++)
  988.         { /* values [j] = b [recv_schedule[j]] */
  989.           ptr = b_zero + recv_schedule[j] * size;
  990.           for (i=0;i<size;i++)
  991.              values [j*size+i] = ptr[i];
  992.         }
  993.     }
  994.  
  995.   /* Step 2: send these values to other processors */
  996.  
  997.   for (k=0; k<nproc; k++)
  998.     if (r_no[k] > 0)
  999.       asend (id, k+1, values + r_ptr[k]*size, r_no[k] * size);
  1000.         
  1001.   free (values);
  1002.  
  1003. } /* dalib_schedule_get_send_ */
  1004.  
  1005. /*********************************************************
  1006. *                                                        *
  1007. *  dalib_schedule_get_recv (a, a_size)                   *
  1008. *                                                        *
  1009. *  - get the requested values and put in in my a         *
  1010. *                                                        *
  1011. *  in :   - a      : my address of array a               *
  1012. *         - a_size : number of bytes of one elem in a    *
  1013. *                                                        *
  1014. *  - uses send_schedule that tells which elements        *
  1015. *    processor got by the other processors               *
  1016. *                                                        *
  1017. *  - use also local_index that tells where to put        *
  1018. *    the received values in my array a                   *
  1019. *                                                        *
  1020. *********************************************************/
  1021.  
  1022. void dalib_schedule_get_recv_ (a, a_size)
  1023.  
  1024. int *a_size;         /* number of bytes for one element */
  1025. unsigned char *a;    /* pointer to first element of a   */
  1026.  
  1027. { int id, nproc;
  1028.   int i, j, k;
  1029.   int size;
  1030.  
  1031.   unsigned char *values;     /* arrays with the received values */
  1032.   unsigned char *ptr;        /* pointer for copy values */
  1033.  
  1034.   id = pcb.i;
  1035.   nproc = pcb.p;
  1036.  
  1037.   /* size of one element of array a */
  1038.  
  1039.   size = *a_size;
  1040.  
  1041.   /* Step 1: recv my values from other processors */
  1042.  
  1043.   values = (unsigned char *) malloc (send_values * size);
  1044. #ifdef MEIKO_CS2
  1045.   ew_touchBuf(values, send_values*size);
  1046. #endif
  1047.  
  1048.   for (k=0; k<nproc; k++)
  1049.     if (s_no[k] > 0)
  1050.       areceive (id, k+1, values + s_ptr[k]*size, s_no[k] * size);
  1051.  
  1052.   /* Step 2: put the values to the right place in array a */
  1053.  
  1054.   if (size == 4)
  1055.     dalib_memgetm4 (a, values, local_index, index_values);
  1056.   else if (size == 8)
  1057.     dalib_memgetm8 (a, values, local_index, index_values);
  1058.   else
  1059.     { for (j=0; j<index_values; j++)
  1060.         { /* a[j] = b [index[j]]  */
  1061.           if (local_index[j] >= 0)               /* only if mask */
  1062.             { ptr = values + local_index[j] * size;
  1063.               for (i=0;i<size;i++)
  1064.                 a[j*size+i] = ptr[i];
  1065.             }
  1066.         }
  1067.     }
  1068.  
  1069.   free (values);
  1070. }
  1071.  
  1072. /*********************************************************
  1073. *                                                        *
  1074. *  dalib_schedule_set_send (a, a_size)                   *
  1075. *                                                        *
  1076. *  - send the values of a to the processors that get it  *
  1077. *                                                        *
  1078. *  in :   - a      : my address of array a               *
  1079. *         - a_size : number of bytes of one elem in a    *
  1080. *                                                        *
  1081. *  - uses local_index that tells how to pack my          *
  1082. *    elements to be sent to other processors             *
  1083. *                                                        *
  1084. *********************************************************/
  1085.  
  1086. void dalib_schedule_set_send_ (a, a_size)
  1087. int *a_size;
  1088. unsigned char *a;
  1089.  
  1090. { int id, nproc;
  1091.   int j, k, i;
  1092.   int size;
  1093.  
  1094.   unsigned char *values;     /* arrays with the values */
  1095.   unsigned char *ptr;        /* pointer for copy values */
  1096.  
  1097.   id = pcb.i;
  1098.   nproc = pcb.p;
  1099.  
  1100.   /* Step 1: use recv_schedudule to get values needed by other processes */
  1101.  
  1102.   /* size of one element of array a */
  1103.  
  1104.   size = *a_size;
  1105.  
  1106.   values = (unsigned char *) malloc (send_values * size);
  1107. #ifdef MEIKO_CS2
  1108.   ew_touchBuf(values, send_values*size);
  1109. #endif
  1110.  
  1111.   for (j=0;j<index_values;j++)
  1112.     { /* values [local_index[j]] = a [j] */
  1113.       if (local_index[j] >= 0)
  1114.         { ptr = values + local_index[j]*size;
  1115.           for (i=0;i<size;i++)
  1116.              ptr[i] = a[j*size+i];
  1117.         }
  1118.     }
  1119.  
  1120.   /* Step 2: send these values to other processors */
  1121.  
  1122.   for (k=0; k<nproc; k++)
  1123.     if (s_no[k] > 0)
  1124.       asend (id, k+1, values + s_ptr[k]*size, s_no[k] * size);
  1125.         
  1126.   free (values);
  1127.  
  1128. } /* dalib_schedule_set_send_ */
  1129.  
  1130. /*********************************************************
  1131. *                                                        *
  1132. *  dalib_schedule_set_recv_ (b_zero, b_size)             *
  1133. *                                                        *
  1134. *     receive values from other processors and are       *
  1135. *     stored/scattered in local part of array b          *
  1136. *                                                        *
  1137. *  in : - b_zero is fiktive zero address of my b         *
  1138. *       - b_size is number of bytes for one elem of b    *
  1139. *                                                        *
  1140. *  -     uses recv_schedule that tells where I have      *
  1141. *        to put the received values                      *
  1142. *                                                        *
  1143. *********************************************************/
  1144.  
  1145. void dalib_schedule_set_recv_ (b_zero, b_size)
  1146.  
  1147. int *b_size;
  1148. unsigned char *b_zero;
  1149.  
  1150. { int id, nproc;
  1151.   int i, j, k;
  1152.   int size;
  1153.  
  1154.   unsigned char *values;     /* arrays with the received values */
  1155.   unsigned char *ptr;        /* pointer for copy values */
  1156.  
  1157.   id = pcb.i;
  1158.   nproc = pcb.p;
  1159.  
  1160.   /* size of one element of array b */
  1161.  
  1162.   size = *b_size;
  1163.  
  1164.   /* Step 1: recv my values from other processors */
  1165.  
  1166.   values = (unsigned char *) malloc (recv_values * size);
  1167. #ifdef MEIKO_CS2
  1168.   ew_touchBuf(values, recv_values*size);
  1169. #endif
  1170.  
  1171.   for (k=0; k<nproc; k++)
  1172.     if (r_no[k] > 0)
  1173.       areceive (id, k+1, values + r_ptr[k]*size, r_no[k] * size);
  1174.  
  1175.   /* Step 2: put the values to the right place in local array b */
  1176.  
  1177.   switch (operation) {
  1178.   case  0 : dalib_set_copy (b_zero, values, size); break;
  1179.   case  1 : dalib_set_min_ints (b_zero, values); break;
  1180.   case  2 : dalib_set_min_reals (b_zero, values); break;
  1181.   case  3 : dalib_set_min_doubles (b_zero, values); break;
  1182.   case  4 : dalib_set_max_ints (b_zero, values); break;
  1183.   case  5 : dalib_set_max_reals (b_zero, values); break;
  1184.   case  6 : dalib_set_max_doubles (b_zero, values); break;
  1185.   case  7 : dalib_set_add_ints (b_zero, values); break;
  1186.   case  8 : dalib_set_add_reals (b_zero, values); break;
  1187.   case  9 : dalib_set_add_doubles (b_zero, values); break;
  1188.   case 10 : dalib_set_mult_ints (b_zero, values); break;
  1189.   case 11 : dalib_set_mult_reals (b_zero, values); break;
  1190.   case 12 : dalib_set_mult_doubles (b_zero, values); break;
  1191.   case 13 : dalib_set_and_ints (b_zero, values); break;
  1192.   case 14 : dalib_set_or_ints (b_zero, values); break;
  1193.   case 15 : dalib_set_eor_ints (b_zero, values); break;
  1194.   case 16 : dalib_set_and_bools (b_zero, values); break;
  1195.   case 17 : dalib_set_or_bools (b_zero, values); break;
  1196.   case 18 : dalib_set_neq_bools (b_zero, values); break;
  1197.   default : dalib_schedule_error ("unknown op for global set"); break;
  1198.   }
  1199.  
  1200.   free (values);
  1201. }
  1202.  
  1203. /*********************************************************
  1204. *                                                        *
  1205. *  dalib_schedule_exit_ ()                               *
  1206. *                                                        *
  1207. *  Reset of a schedule, frees the memory                 *
  1208. *                                                        *
  1209. *********************************************************/
  1210.  
  1211. void dalib_schedule_exit_ ()
  1212.  
  1213. {
  1214.   free (recv_schedule);
  1215.   free (r_ptr);
  1216.   free (r_no);
  1217.   free (local_index);
  1218.   /* free (send_schedule) has already been done */
  1219.   free (s_ptr);
  1220.   free (s_no);
  1221. } /* dalib_schedule_exit */
  1222.  
  1223. /***********************************************************************
  1224. *                                                                      *
  1225. *  Check Routines                                                      *
  1226. *                                                                      *
  1227. *  check1 : A , B [P], MASK                                            *
  1228. *  check2 : A , B [P,Q], MASK                                          *
  1229. *                                                                      *
  1230. *    - P, Q must be integer*4                                          *
  1231. *    - MASK must be logical*4                                          *
  1232. *    - A, B must be of same type                                       *
  1233. *    - A, P, Q, MASK must be of same shape                             *
  1234. *    - rank of B must be 1 (check1) or 2 (check2)                      *
  1235. *                                                                      *
  1236. ***********************************************************************/
  1237.  
  1238. /*******************************************************************
  1239. *                                                                  *
  1240. *  MASK: A = B [P]  : A[j] = B[P[j]]    for all j with MASK(j)     *
  1241. *                                                                  *
  1242. *  void dalib_global_getm1_ (a, a_size, a_elems,                   *
  1243. *                            b, b_N1, p, mask   )                  *
  1244. *                                                                  *
  1245. *******************************************************************/
  1246.  
  1247. void dalib_global_getm1_ (a, a_size, a_elems, b, b_N1, p, mask)
  1248.  
  1249. int *a_size;    /* number of local elements of a and p */
  1250. int *a_elems;   /* number of elemens in a, p           */
  1251. int *b_N1;      /* number of elements of b             */
  1252. int *p, *mask;  /* p == mask if mask is not available  */
  1253. unsigned char *a, *b;
  1254.  
  1255. { unsigned char *b_zero;
  1256.  
  1257.   /* Step 1: init schedule */
  1258.  
  1259.   /* a_elems is also number of local elements for index array p */
  1260.   dalib_schedule_init_ (b_N1, p, a_elems, mask);
  1261.  
  1262.   /* Step 2: define schedule */
  1263.  
  1264.   dalib_schedule_send_ (b_N1, p);
  1265.   dalib_schedule_recv_ ();
  1266.  
  1267.   /* Step 3: make get with schedule */
  1268.  
  1269.   b_zero = dalib_array_zero1 (b, *a_size, *b_N1);
  1270.   dalib_schedule_get_send_ (b_zero, a_size);   /* send requested values of b */
  1271.  
  1272.   dalib_schedule_get_recv_ (a, a_size);
  1273.  
  1274.   /* Step 4: release schedule */
  1275.  
  1276.   dalib_schedule_exit_ ();
  1277.  
  1278. } /* dalib_global_getm1 */
  1279.  
  1280. /*******************************************************************
  1281. *                                                                  *
  1282. *  MASK: B [P] = A  : B[P[j]] = A[j]    for all j with MASK(j)     *
  1283. *                                                                  *
  1284. *  void dalib_global_setm1_ (op, b, b_N1, p,                       *
  1285. *                            a, a_size, a_elems, mask)             *
  1286. *                                                                  *
  1287. *******************************************************************/
  1288.  
  1289. void dalib_global_setm1_ (op, b, b_N1, p, a, a_size, a_elems, mask)
  1290.  
  1291. unsigned char *a, *b;
  1292. int *op;
  1293. int *a_size, *a_elems;
  1294. int *p, *mask;
  1295. int *b_N1;
  1296.  
  1297. { unsigned char *b_zero;
  1298.  
  1299.   /* make assertions  */
  1300.  
  1301.   operation = *op;      /* global set for operation */
  1302.  
  1303.   /* Step 1: init schedule */
  1304.  
  1305.   /* a_elems is also number of local elements for index array p */
  1306.  
  1307.   dalib_schedule_init_ (b_N1, p, a_elems, mask);
  1308.  
  1309.   /* Step 2: define schedule */
  1310.  
  1311.   dalib_schedule_send_ (b_N1, p);
  1312.   dalib_schedule_recv_ ();
  1313.  
  1314.   /* Step 3: make set with schedule */
  1315.  
  1316.   dalib_schedule_set_send_ (a, a_size);
  1317.   b_zero = dalib_array_zero1 (b, *a_size, *b_N1);
  1318.   dalib_schedule_set_recv_ (b_zero, a_size);
  1319.  
  1320.   /* Step 4: release schedule */
  1321.  
  1322.   dalib_schedule_exit_ ();
  1323.  
  1324. } /* dalib_global_setm1 */
  1325.  
  1326. /***********************************************************************
  1327. *                                                                      *
  1328. *  MASK: A = B [P,Q]  : A[j] = B[P[j],Q[j]]    for all j with MASK(j)  *
  1329. *                                                                      *
  1330. *  void dalib_global_getm2_ (a, a_size, a_elems,                       *
  1331. *                            b, b_N1, b_N2, p, q, mask   )             *
  1332. *                                                                      *
  1333. ***********************************************************************/
  1334.  
  1335. void dalib_global_getm2_ (a, a_size, a_elems, b, b_N1, b_N2, p, q, mask)
  1336.  
  1337. int *a_size;        /* number of bytes for elem size of a and b */
  1338. int *a_elems;       /* number of local elements in a, p, q */
  1339. int *b_N1, *b_N2;    /* global dimensions of b */
  1340. int *p, *q, *mask;  /* q == mask if mask is not available */
  1341. unsigned char *a, *b;
  1342.  
  1343. { unsigned char *b_zero;
  1344.  
  1345.   /* make assertions */
  1346.  
  1347. #ifdef DEBUG
  1348.   printf ("Process %d starts getm2\n", pcb.i);
  1349. #endif
  1350.  
  1351.   /* Step 1: init schedule */
  1352.  
  1353.   /* a_elems is also number of local elements for index array q */
  1354.   dalib_schedule_init_ (b_N2, q, a_elems, mask);
  1355.  
  1356.   /* Step 2: define schedule */
  1357.  
  1358.   dalib_schedule_send2_ (b_N1, b_N2, p, q);
  1359.   dalib_schedule_recv_ ();
  1360.  
  1361.   /* Step 3: make get with schedule */
  1362.  
  1363.   b_zero = dalib_array_zero2 (b, *a_size, *b_N1, *b_N2);
  1364.   dalib_schedule_get_send_ (b_zero, a_size);
  1365.  
  1366.   dalib_schedule_get_recv_ (a, a_size);
  1367.  
  1368.   /* Step 4: release schedule */
  1369.  
  1370.   dalib_schedule_exit_ ();
  1371.  
  1372. } /* dalib_global_getm2 */
  1373.  
  1374. /***********************************************************************
  1375. *                                                                      *
  1376. *  MASK: B [P,Q] = A  : B[P[j],Q[j]] = A[j]    for all j with MASK(j)  *
  1377. *                                                                      *
  1378. *  void dalib_global_setm2_ (op, b, b_N1, b-N2, p, q                   *
  1379. *                            a, a_size, a_elems, mask)                 *
  1380. *                                                                      *
  1381. ***********************************************************************/
  1382.  
  1383. void dalib_global_setm2_ (op, b, b_N1, b_N2, p, q,
  1384.                               a, a_size, a_elems,   mask)
  1385. int *op;
  1386. int *a_size;        /* number of bytes for elem size of a and b */
  1387. int *a_elems;       /* number of local elements in a, p, q */
  1388. int *b_N1, *b_N2;   /* global dimensions of b */
  1389. int *p, *q, *mask;  /* q == mask if mask is not available */
  1390. unsigned char *a, *b;
  1391.  
  1392. { unsigned char *b_zero;
  1393.  
  1394.   operation = *op;    /* global set of scatter operation */
  1395.  
  1396.   /* Step 1: init schedule */
  1397.  
  1398.   /* a_elems is also number of local elements for index array q */
  1399.   dalib_schedule_init_ (b_N2, q, a_elems, mask);
  1400.  
  1401.   /* Step 2: define schedule */
  1402.  
  1403.   dalib_schedule_send2_ (b_N1, b_N2, p, q);
  1404.   dalib_schedule_recv_ ();
  1405.  
  1406.   /* Step 3: make set with schedule */
  1407.  
  1408.   dalib_schedule_set_send_ (a, a_size);   /* values of b will be send */
  1409.  
  1410.   b_zero = dalib_array_zero2 (b, *a_size, *b_N1, *b_N2);
  1411.   dalib_schedule_set_recv_ (b_zero, a_size);      /* recv values in b */
  1412.  
  1413.   /* Step 4: release schedule */
  1414.  
  1415.   dalib_schedule_exit_ ();
  1416.  
  1417. } /* dalib_global_setm2 */
  1418.  
  1419. /*******************************************************************
  1420. *                                                                  *
  1421. *  FORTRAN INTERFACE                                               *
  1422. *                                                                  *
  1423. *  void dalib_global_switch_ (a, a_size, a_elems, b, b_N1, p)      *
  1424. *                                                                  *
  1425. *******************************************************************/
  1426.  
  1427. void dalib_global_switch_ (a, a_size, a_elems, b, b_N1, p)
  1428. unsigned char *a, *b;
  1429. int *a_size, *a_elems, *b_N1;
  1430. int *p;
  1431.  
  1432. { unsigned char *b_zero;
  1433.  
  1434.   /* Step 1: init schedule */
  1435.  
  1436.   dalib_switching_init_ (b_N1, p, a_elems);
  1437.  
  1438.   /* Step 2: define schedule */
  1439.  
  1440.   dalib_schedule_send_ (b_N1, p);
  1441.   dalib_schedule_recv_ ();
  1442.  
  1443.   /* Step 3: make get with schedule */
  1444.  
  1445.   b_zero = dalib_array_zero1 (b, *a_size, *b_N1);
  1446.   dalib_schedule_get_send_ (b_zero, a_size);
  1447.   dalib_schedule_get_recv_ (a, a_size);
  1448.  
  1449.   /* Step 4: release schedule */
  1450.  
  1451.   dalib_schedule_exit_ ();
  1452.  
  1453. } /* dalib_global_switch */
  1454.  
  1455. /*******************************************************************
  1456. *                                                                  *
  1457. *  FORTRAN INTERFACE                                               *
  1458. *                                                                  *
  1459. *    - subroutines without a mask parameter                        *
  1460. *                                                                  *
  1461. *******************************************************************/
  1462.  
  1463. void dalib_global_get1_ (a, a_size, a_elems, b, b_N1, p)
  1464.  
  1465. int *a_size;    /* size of elements of a and b in Bytes */
  1466. int *a_elems;   /* number of elements in a and p        */
  1467. int *b_N1;      /* number of elements of b */
  1468. int *p;
  1469. unsigned char *a, *b;
  1470.  
  1471. { /* mask = p means no mask */
  1472.  
  1473.    dalib_global_getm1_ (a, a_size, a_elems, b, b_N1, p, p);
  1474. }
  1475.  
  1476. void dalib_global_get2_ (a, a_size, a_elems, b, b_N1, b_N2, p, q)
  1477. int *a_size;        /* number of bytes for elem size of a and b */
  1478. int *a_elems;       /* number of local elements in a, p, q */
  1479. int *b_N1, b_N2;    /* global dimensions of b */
  1480. int *p, *q;
  1481. unsigned char *a, *b;
  1482.  
  1483. { /* mask = p means no mask */
  1484.    dalib_global_getm2_ (a, a_size, a_elems, b, b_N1, b_N2, p, q, q);
  1485. }
  1486.  
  1487. /*******************************************************************
  1488. *                                                                  *
  1489. *  FORTRAN INTERFACE                                               *
  1490. *                                                                  *
  1491. *    - splitted subroutines to reuse a fixed schedule              *
  1492. *                                                                  *
  1493. *******************************************************************/
  1494.  
  1495. void dalib_schedule_fix1__ (b_N1, p, p_elems, mask)
  1496. int *p_elems;   /* number of elemens in p           */
  1497. int *b_N1;      /* number of elements of b           */
  1498. int *p, *mask;  /* p == mask if mask is not available  */
  1499.  
  1500. { dalib_schedule_init_ (b_N1, p, p_elems, mask);
  1501.   dalib_schedule_send_ (b_N1, p);
  1502.   dalib_schedule_recv_ ();
  1503. }
  1504.  
  1505. void dalib_schedule_fix2__ (b_N1, b_N2, p, q, q_elems, mask)
  1506. int *q_elems;   /* number of elemens in q           */
  1507. int *b_N1;      /* number of elements of b           */
  1508. int *b_N2;      /* number of elements of b           */
  1509. int *p, *q, *mask;  /* q == mask if mask is not available  */
  1510.  
  1511. { dalib_schedule_init_ (b_N1, q, q_elems, mask);
  1512.   dalib_schedule_send2_ (b_N1, b_N2, p, q);
  1513.   dalib_schedule_recv_ ();
  1514. }
  1515.  
  1516. void dalib_schedule_get1__ (b, b_N1, a, size)
  1517.  
  1518. unsigned char *b, *a;
  1519. int *b_N1, *size;
  1520.  
  1521. { unsigned char *b_zero;
  1522.   b_zero = dalib_array_zero1 (b, *size, *b_N1);
  1523.   dalib_schedule_get_send_ (b_zero, size);
  1524.   dalib_schedule_get_recv_ (a, size);
  1525. }
  1526.  
  1527. void dalib_schedule_get2__ (b, b_N1, b_N2, a, size)
  1528.  
  1529. unsigned char *b, *a;
  1530. int *b_N1, *b_N2, *size;
  1531.  
  1532. { unsigned char *b_zero;
  1533.   b_zero = dalib_array_zero2 (b, *size, *b_N1, *b_N2);
  1534.   dalib_schedule_get_send_ (b_zero, size);
  1535.   dalib_schedule_get_recv_ (a, size);
  1536. }
  1537.  
  1538. void dalib_schedule_set1__ (op, b, b_N1, a, a_size)
  1539.  
  1540. unsigned char *a, *b;
  1541. int *op;
  1542. int *a_size, *b_N1;
  1543.  
  1544. { unsigned char *b_zero;
  1545.   operation = *op;      /* global set for operation */
  1546.   dalib_schedule_set_send_ (a, a_size);
  1547.   b_zero = dalib_array_zero1 (b, *a_size, *b_N1);
  1548.   dalib_schedule_set_recv_ (b_zero, a_size);
  1549.  
  1550. } /* dalib_schedule_set1 */
  1551.  
  1552. void dalib_schedule_set2__ (op, b, b_N1, b_N2, a, a_size)
  1553.  
  1554. unsigned char *a, *b;
  1555. int *op;
  1556. int *a_size, *b_N1, *b_N2;
  1557.  
  1558. { unsigned char *b_zero;
  1559.   operation = *op;      /* global set for operation */
  1560.   dalib_schedule_set_send_ (a, a_size);
  1561.   b_zero = dalib_array_zero1 (b, *a_size, *b_N1, *b_N2);
  1562.   dalib_schedule_set_recv_ (b_zero, a_size);
  1563.  
  1564. } /* dalib_schedule_set2 */
  1565.  
  1566.  
  1567.